<template>
	<n-layout-content content-class="flex flex-col gap-2" class="p-2">
		<n-text class="text-2xl">接收工程遥测
			<n-text depth="3">(停止接收时, 请打开[串口设置]页面, 直接关闭掉串口即可!</n-text>
		</n-text>

		<n-flex align="center">
			<n-text>文件名称:</n-text>
			<n-input class="w-fit" v-model:value="suggestedName">
				<template #suffix>
					<n-text depth="3">.bin</n-text>
				</template>
			</n-input>
			<n-button @click="main" type="success">选择文件保存(点击开始接收)</n-button>
			<n-button @click="logBuffer.splice(0,logBuffer.length)" type="error">清空日志</n-button>

		</n-flex>
		<n-flex class="w-1/2">
			<n-text>接收日志:</n-text>
			<n-virtual-list ref="virtualListInst"
							class="bg-zinc-800 h-150 max-h-full p-2"
							:item-size="72"
							item-resizable
							:items="logBuffer">
				<template #default="{ item, index }">
					<div :key="item.key">
						<n-text class="w-fit font-mono text-base break-words whitespace-pre-wrap">
							{{ item.content.toUpperCase() }}
						</n-text>
					</div>
				</template>
			</n-virtual-list>
		</n-flex>
	</n-layout-content>


</template>

<script lang="ts" setup>
import {onMounted, ref, computed, watchEffect, nextTick, reactive} from 'vue'
import {useUserProfile} from "@/stores/useUserProfile"
import {storeToRefs} from "pinia";
import {generateRandomKey} from "@/utils/byteParser"
import {uint8ArrayToHexString} from "@/utils/byteParser"
import {useNotification} from "naive-ui";

const userProfile = useUserProfile()
const notification = useNotification()
const {profile} = storeToRefs(userProfile);

// 日志字符串
const logString = ref('')
// 日志dom元素
const virtualListInst = ref(null)
// 工程数据页
const scdTab = computed(() => profile.value.tabList.find(tab => tab.asLabel === "captureData"))
const suggestedName = ref("data")
let reader;
// 日志内容
const logBuffer = reactive([]); // 缓冲区存储日志数据


async function readSerialData(readableStream, handleChunk) {

	reader = readableStream.getReader();
	scdTab.value.reader = reader
	// 此处接收不到scdTab
	try {
		while (scdTab.value.connected && scdTab.value.port.readable) {
			try {
				const {value, done} = await reader.read()

				if (done) {
					console.log("读取完成或停止标志已触发");
					break;
				}

				// 更新字符串
				logBuffer.push({
					key: generateRandomKey(),
					content: uint8ArrayToHexString(value)
				})
				// 处理写入块
				await handleChunk(value);
				await new Promise(resolve => setTimeout(resolve, 10));

			} catch (error) {
				console.error(error)
			}
		}
	} finally {
		console.log("释放读取器");
		reader.releaseLock();
	}
	console.log(scdTab)
	scdTab.value.port.readable && await scdTab.value.port.close()
	console.log("关闭了串口")
}


async function main() {
	// 打开文件保存句柄
	const fileHandle = await showSaveFilePicker({
		suggestedName: suggestedName.value + ".bin",
		types: [
			{
				description: 'Text Files',
				accept: {'text/plain': ['.txt']},
			},
			{
				description: 'Binary Files',
				accept: {'application/octet-stream': ['.bin']},
			},
		],
	});
	const writer = await fileHandle.createWritable();

// 定义处理数据块的函数
	async function handleChunk(value) {
		// 将数据块直接写入文件
		await writer.write(value);
	}


	console.log(scdTab)
	notification.success({title: "开始接收工程数据..."})
	// 从串口读取数据并处理
	await readSerialData(scdTab.value.port.readable, handleChunk);


	// 完成后关闭文件
	await writer.close();
	notification.success({title: "文件已保存", content: new Date().toLocaleString()});
}

onMounted(() => {
	// 根据
	watchEffect(() => {
		if (logBuffer.length) {
			nextTick(() => {
				console.log("trigger!!!")
				virtualListInst.value?.scrollTo({position: 'bottom', silent: true, smooth: true})
			})
		}
	})
})

</script>
<style scoped>
.item {
	display: flex;
	align-items: flex-start;
}
</style>